home *** CD-ROM | disk | FTP | other *** search
/ Super PC 28 / Super PC 28 (Shareware para Windows 95 y MS-DOS).iso / spc / win / dido3 / source / didod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-15  |  7.9 KB  |  308 lines

  1.  
  2. // Routines to make calls to the real-mode CDROM driver from protected-mode Windows,
  3. // Using GlobalDOSAlloc and DPMI's int86x service.
  4.  
  5. // These are allocated in real-mode DOS memory:
  6.  
  7. DWORD cmdbuf=0,                // Buffer for commands, device driver request headers, etc...
  8.       databuf=0,            // Buffer for actual data
  9.       buf[MAXNBUF],            // Buffer for reading audio data
  10.       prev_end=0;            // Buffer for synchronization
  11.  
  12. WORD cmdbufseg,cmdbufsel,
  13.      databufseg,databufsel, // The same as above, but split into SEG/SEL pairs
  14.      bufseg[MAXNBUF],bufsel[MAXNBUF],
  15.      prev_endseg, prev_endsel;
  16.  
  17. BYTE *pcmdbuf=0,            // Pointers the program can use to access above memory areas
  18.      *pdatabuf=0,
  19.      *pprev_end=0,
  20.      *pbuf[MAXNBUF];
  21.  
  22. // Set things up to interact with the CDROM driver. Returns 0:Failure, 1:Success
  23. int startinterfacing(void)
  24. {
  25.     int i;
  26.  
  27.     memset(buf,0,sizeof(buf));        // zap buffer pointers
  28.  
  29.     cmdbuf=GlobalDosAlloc(32);        // 32 bytes for command buffer (BTW, is at most 26 bytes)
  30.     cmdbufseg=HIWORD(cmdbuf); 
  31.     cmdbufsel=LOWORD(cmdbuf); 
  32.     pcmdbuf=MK_FP(cmdbufsel,0);
  33.  
  34.     if (!cmdbuf) goto Allocerror;          
  35.  
  36.     databuf=GlobalDosAlloc(4096);    // general purpose data buffer
  37.     databufseg=HIWORD(databuf); 
  38.     databufsel=LOWORD(databuf); 
  39.     pdatabuf=MK_FP(databufsel,0); 
  40.  
  41.     if (!databuf) goto Allocerror;
  42.  
  43.     prev_end=GlobalDosAlloc((long)FRAME_SIZE * NBLOCK);
  44.     prev_endseg=HIWORD(prev_end); 
  45.     prev_endsel=LOWORD(prev_end); 
  46.     pprev_end=MK_FP(prev_endsel,0);
  47.     if (!prev_end) goto Allocerror;
  48.  
  49.     // Try to allocate as much data buffers if possible, up to MAXNBUF
  50.  
  51.     nbuf=0;
  52.     for (i=0;i<MAXNBUF;i++) {
  53.         buf[nbuf]=GlobalDosAlloc((long)FRAME_SIZE*NBLOCK);
  54.         bufseg[nbuf]=HIWORD(buf[nbuf]);
  55.         bufsel[nbuf]=LOWORD(buf[nbuf]);
  56.         pbuf[nbuf]=MK_FP(bufsel[nbuf],0);
  57.         if (!buf[nbuf]) {
  58.             if (nbuf<2) goto Allocerror;
  59.             break;
  60.             }
  61.         nbuf++;
  62.         }
  63.  
  64.     return 1;                                                    // success
  65.  
  66. Allocerror:
  67.  
  68.     for (i=0;i<nbuf;i++) if (buf[i]) GlobalDosFree(bufsel[i]);
  69.     if (cmdbuf) GlobalDosFree(cmdbufsel);
  70.     if (databuf) GlobalDosFree(databufsel);
  71.     if (prev_end) GlobalDosFree(prev_endsel);
  72.     return 0;                                                    // failure
  73. }
  74.  
  75.  
  76. // Free the real-mode buffers
  77. int stopinterfacing(void)
  78. {
  79.     int i;
  80.     for (i=0;i<nbuf;i++) GlobalDosFree(bufsel[i]);
  81.     GlobalDosFree(cmdbufsel);
  82.     GlobalDosFree(databufsel);
  83.     GlobalDosFree(prev_endsel);
  84.     return 1;
  85. }
  86.  
  87. // Used for DPMI call
  88. struct realregs {
  89.     DWORD edi,esi,ebp,resvd,ebx,edx,ecx,eax;
  90.     WORD flags,es,ds,fs,gs,ip,cs,sp,ss; 
  91.     };
  92.  
  93. int dpmint86(int intnr,struct realregs *in,struct realregs *out)
  94. {
  95.     union REGS inregs, outregs; 
  96.     struct SREGS sregs; 
  97.     struct realregs *r; 
  98.      
  99.     memset(&inregs,0,sizeof(union REGS));        // Just to be sure there is no junk... 
  100.     memset(&outregs,0,sizeof(union REGS)); 
  101.     memset(&sregs,0,sizeof(struct SREGS)); 
  102.  
  103.     inregs.x.ax=0x0300;                         // Simulate Real Mode Interrupt 
  104.     inregs.x.bx=intnr;                             // interrupt # 
  105.     inregs.x.di=FP_OFF(in);                     // address of struct regs
  106.     sregs.es=FP_SEG(in);                        //     ,, 
  107.     int86x(0x31,&inregs,&outregs,&sregs);        // Call real mode INT via DPMI 
  108.     if (outregs.x.cflag) {
  109.         mb("DPMI interface returned error");
  110.         return 1;                                // DPMI gave error? Exit.
  111.         } 
  112.     r=MK_FP(sregs.es, outregs.x.di);            // Where to find the output 
  113.     if(r->flags & 1) {
  114.         mb("INT2F returned error");
  115.         return 1;                                // Interrupt in error? Test for carry, exit if 1
  116.         }
  117.     memcpy(out,r,sizeof(struct realregs));        // Get result registers back
  118.     return 0; 
  119. }
  120.  
  121. // Is MSCDEX installed? (No need for DPMI using this call)
  122. int CheckMscdex(void)
  123. {
  124.     union REGS reg;
  125.     reg.x.ax=0x1500;                            // MSCDEX - Get number of CDROM drives
  126.     reg.x.bx=0;
  127.     int86(0x2f, ®, ®);
  128.     if (!reg.x.bx) return 0;                    // Nr. of CDROM drives in bx
  129.     CDROM=reg.x.cx;                                // CX=first CDROM drive (A==0, B==1, etc)
  130.     return 1;
  131. }
  132.  
  133. // Call CDROM device driver; command-buffer (at pcmdbuf) must be filled by caller
  134. void CallDriver(void)
  135. {
  136.     struct realregs r;                            // Prepare registers
  137.     memset(&r,0,sizeof(r));
  138.     r.eax=0x1510;                                // Function: CDROM device driver request
  139.     r.es=cmdbufseg; r.ebx=0;                    // Address of request structure 
  140.     r.ecx=CDROM;                                // Drive number of CDROM
  141.     dpmint86(0x2f,&r,&r);
  142. }
  143.  
  144. // Get CDROM disk information
  145. int GetDiskInfo(void)
  146. {
  147.     struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
  148.     struct DiskInfo *pdi=(struct DiskInfo *)pdatabuf;
  149.  
  150.     pcmd->req.len=26;
  151.     pcmd->req.unit=0;
  152.     pcmd->req.command=3;
  153.     pcmd->descriptor=0;
  154.     pcmd->address=MK_FP(databufseg,0);
  155.     pcmd->len=7;
  156.     pcmd->secnum=0;
  157.     pcmd->ptr=0;
  158.     pdi ->control=10;
  159.  
  160.     CallDriver();
  161.  
  162.     lowest =pdi->lowest;
  163.     highest=pdi->highest;
  164.     total_time=pdi->total;
  165.     return pcmd->req.status;
  166. }
  167.  
  168.  
  169. // Read one or more raw audio sectors
  170. int ReadLong(DWORD loc, WORD secnum,WORD bufseg)
  171. {
  172.     struct ReadL *pcmd=(struct ReadL *)pcmdbuf;
  173.     pcmd->req.len=sizeof(struct ReadL);
  174.     pcmd->req.unit=0;
  175.     pcmd->req.command=128;
  176.     pcmd->mode=0;
  177.     pcmd->address=MK_FP(bufseg,0);
  178.     pcmd->secnum=secnum;
  179.     pcmd->loc=loc;
  180.     pcmd->readmode=RAW_MODE;
  181.     pcmd->skip[0]=pcmd->skip[1]=0;
  182.     CallDriver();
  183.     return pcmd->req.status;
  184. }
  185.  
  186.  
  187. // Convert sector number to printable MM:SS:FF string, for durations.
  188. char *Sector2MSF(DWORD sector)
  189. {
  190.     static char s[20];
  191.     long min,sec,frames;
  192.     frames=sector%75;
  193.     sec=sector/75;
  194.     min=sec/60; sec=sec%60;
  195.     sprintf(s,"%02ldm %02lds %02ldf",min,sec,frames);
  196.     return s;
  197. }
  198.  
  199. // Convert Sierra sector number to redbook
  200. DWORD Sierra2Red(DWORD sierra)
  201. {
  202.     DWORD min,sec,frame,loc;
  203.     sierra+=150;                         /// ????????????
  204.     frame=sierra%75;
  205.     sec=sierra/75;
  206.     min=sec/60; sec=sec%60;
  207.  
  208.     loc=(BYTE)min;
  209.     loc<<=8;    loc|=(BYTE)sec;
  210.     loc<<=8;    loc|=(BYTE)frame;
  211.     return loc;
  212. }
  213.  
  214.  
  215. // Convert redbood time location to Sierra sector
  216. DWORD Red2Sierra(DWORD loc)
  217. {
  218.     BYTE min,sec,frame;
  219.     min=(loc>>16)&0xff;
  220.     sec=(loc>>8)&0xff;
  221.     frame=loc&0xff;
  222.     return (DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
  223. }
  224.  
  225.  
  226. // Convert redbook time location to printable string
  227. char *Red2MSF(DWORD loc)
  228. {
  229.     static char s[20];
  230.     BYTE min,sec,frame;
  231.     min=(loc>>16)&0xff;
  232.     sec=(loc>>8)&0xff;
  233.     frame=loc&0xff;
  234.     sprintf(s,"%02um %02us %02uf",min,sec,frame);
  235.     return s;
  236. }
  237.  
  238.  
  239. // Convert redbook time location to minute, second, frame, and Sierra sector
  240. void Red2MSFC(DWORD loc,WORD *min,WORD *sec,WORD *frame,DWORD *sector)
  241. {
  242.     *frame=loc&0xff;
  243.     loc>>=8;    *sec=loc&0xff;
  244.     loc>>=8;    *min=loc&0xff;
  245.     *sector=((DWORD)*min)*75*60+((DWORD)*sec)*75+((DWORD)*frame)-150;
  246. }
  247.  
  248.  
  249. // Convert minute, second, frame to redbook timecode and Sierra sector
  250. void MSF2Red(WORD min,WORD sec,WORD frame,DWORD *red,DWORD *sector)
  251. {
  252.     DWORD loc=0;
  253.     *sector=(DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
  254.     loc|=min; loc<<=8;
  255.     loc|=sec; loc<<=8;
  256.     loc|=frame;
  257.     *red=loc;
  258. }
  259.  
  260.  
  261. // Ask the CDROM device driver information about a track.
  262. // Given the track number, find out at which sector it starts
  263. int GetTrackInfo(int track,DWORD *loc)
  264. {
  265.     struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
  266.     struct TrackInfo *pbuf=(struct TrackInfo *)pdatabuf;
  267.     pcmd->req.len=26;
  268.     pcmd->req.unit=0;
  269.     pcmd->req.command=3;
  270.     pcmd->descriptor=0;
  271.     pcmd->address=MK_FP(databufseg,0);
  272.     pcmd->len=7;
  273.     pcmd->secnum=0;
  274.     pcmd->ptr=0;
  275.     pbuf->control=11;
  276.     pbuf->track=track;
  277.     CallDriver();
  278.     *loc=pbuf->loc;
  279.     return pcmd->req.status;
  280. }
  281.  
  282.  
  283. // Stop playing of current audio piece
  284. int StopAudio(void)
  285. {
  286.     struct ReqHdr *pcmd=(struct ReqHdr *)pcmdbuf;
  287.     pcmd->len=13;
  288.     pcmd->unit=0;
  289.     pcmd->command=133;
  290.     CallDriver();
  291.     return pcmd->status;
  292. }
  293.  
  294.  
  295. // Play an piece of audio
  296. int PlayAudio(DWORD loc, DWORD num)
  297. {
  298.     struct PlayReq *pcmd=(struct PlayReq *)pcmdbuf;
  299.     pcmd->req.len=22;
  300.     pcmd->req.unit=0;
  301.     pcmd->req.command=132;
  302.     pcmd->mode=1;
  303.     pcmd->loc=loc;
  304.     pcmd->secnum=num;
  305.     CallDriver();
  306.     return pcmd->req.status;
  307. }
  308.